package io.api.modules.project.controller;


import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.ImmutableBiMap;
import io.admin.common.constant.Constant;
import io.admin.common.exception.ErrorCode;
import io.admin.common.page.PageData;
import io.admin.common.utils.Result;
import io.admin.common.validator.AssertUtils;
import io.admin.common.validator.ValidatorUtils;
import io.admin.common.validator.group.AddGroup;
import io.admin.common.validator.group.DefaultGroup;
import io.admin.common.validator.group.UpdateGroup;

import io.api.config.RoughInType;
import io.api.modules.project.dto.AnchorDTO;
import io.api.modules.project.dto.AnchorMileageDTO;
import io.api.modules.project.dto.AnchorSortDTO;
import io.api.modules.project.dto.PageAnchorDTO;
import io.api.modules.project.entity.AnchorEntity;
import io.api.modules.project.service.AnchorService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * 定位点
 *
 * @author Mark sunlightcs@gmail.com
 * @since 1.0.0 2024-07-09
 */
@RestController
@RequestMapping("/api/anchor")
@Api(tags="定位点")
public class AnchorController {

    @Autowired
    private AnchorService anchorService;

    @Autowired
    private RoughInType roughInType;

    @GetMapping("page")
    @ApiOperation("分页")
    @ApiImplicitParams({
        @ApiImplicitParam(name = Constant.LIMIT, value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
        @ApiImplicitParam(name = Constant.ORDER_FIELD, value = "排序字段", paramType = "query", dataType="String") ,
        @ApiImplicitParam(name = Constant.ORDER, value = "排序方式，可选值(asc、desc)", paramType = "query", dataType="String")
    })
    public Result<PageData<PageAnchorDTO>> page(@ApiIgnore @RequestParam Map<String, Object> params){
        if (Objects.nonNull(params.get("projectId"))) {
            String projectIdStr = (String) params.get("projectId");
            Long projectId = Long.parseLong(projectIdStr);
            params.put("projectId", projectId);
        }
        if (Objects.nonNull(params.get("lineId"))) {
            String lineIdStr = (String) params.get("lineId");
            Long lineId = Long.parseLong(lineIdStr);
            params.put("lineId", lineId);
        }
        PageData<PageAnchorDTO> page = anchorService.pageAnchors(params);
        return new Result<PageData<PageAnchorDTO>>().ok(page);
    }

    @GetMapping("exist")
    public Result exist(
            @RequestParam(value = "lineId") Long lineId,
            @RequestParam(value = "name") String name,
            @RequestParam(value = "anchorId", required = false) Long anchorId
    ){
        if (anchorService.countByNameAndLineId(name, lineId, anchorId) > 0) {
            return new Result().error("定位点名称已存在");
        } else {
            return new Result().ok("定位点不存在");
        }
    }

    @GetMapping("{id}")
    @ApiOperation("信息")
    public Result get(@PathVariable("id") Long id){
        AnchorDTO anchorDTO = anchorService.get(id);
        if (Objects.isNull(anchorDTO)) {
            return new Result<>().error(ErrorCode.NOT_NULL, "查不到对应信息");
        }
        return new Result().ok(anchorDTO);
    }

    @PostMapping
    @ApiOperation("保存")
    public Result save(@RequestBody AnchorDTO dto){

        //效验数据
        ValidatorUtils.validateEntity(dto,AddGroup.class, DefaultGroup.class);
        if (anchorService.countByNameAndLineId(dto.getName(), dto.getLineId(), null) > 0) {
            return new Result().error(ErrorCode.DB_RECORD_EXISTS);
        }
        AnchorEntity anchor =  anchorService.insert(dto);
        return new Result().ok(ImmutableBiMap.of("id", anchor.getId()));
    }

    @PutMapping
    @ApiOperation("修改")
    public Result update(@RequestBody AnchorDTO dto){
        //效验数据
        ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
        if (anchorService.countByNameAndLineId(dto.getName(), dto.getLineId(), dto.getId()) > 0) {
            return new Result().error(ErrorCode.DB_RECORD_EXISTS);
        }
        anchorService.update(dto);
        return new Result();
    }

    @PutMapping("sort")
    @ApiOperation("定位点排序")
    public Result sort(@RequestBody List<AnchorSortDTO> dtos){
        //效验数据
        List<AnchorEntity> entities = dtos.stream().map(i -> {
            ValidatorUtils.validateEntity(i);
            AnchorEntity anchor = new AnchorEntity();
            anchor.setId(i.getId());
            anchor.setSort(i.getSort());
            return anchor;
        }).collect(Collectors.toList());
        if (anchorService.updateBatchById(entities)) {
            return new Result();
        }
        return new Result().error("排序失败");
    }

    @DeleteMapping("{id}")
    @ApiOperation("删除")
    public Result delete(@PathVariable Long id){
        anchorService.deleteById(id);
        return new Result();
    }

    @DeleteMapping
    @ApiOperation("批量删除")
    public Result deleteBatch(@RequestBody Long[] ids){
        //效验数据
        AssertUtils.isArrayEmpty(ids, "id");
        anchorService.delete(ids);
        return new Result();
    }

    @GetMapping("list/line/{lineId}")
    public Result<List<AnchorDTO>> list(@PathVariable Long lineId) {
        List<AnchorDTO> list = anchorService.list(lineId);
        return new Result<List<AnchorDTO>>().ok(list);
    }

    @GetMapping("list/project/{projectId}")
    public Result<List<AnchorDTO>> listByProjectId(@PathVariable Long projectId) {
        List<AnchorDTO> list = anchorService.listByProjectId(projectId);
        return new Result<List<AnchorDTO>>().ok(list);
    }

    @GetMapping("roughInType")
    public Result getRoughInType() {
        return new Result().ok(roughInType.getMap());
    }

    @GetMapping("list/lineMileageList/{lineId}")
    public Result<List<AnchorMileageDTO>> lineList(@PathVariable Long lineId) {
        List<AnchorDTO> list = anchorService.list(lineId);
        if(CollectionUtil.isEmpty(list)){
            return new Result<List<AnchorMileageDTO>>().ok(new ArrayList<>());
        }
        List<AnchorMileageDTO> listAnchorMileageDTO = new ArrayList<>();
        int index =0;
        double count =0;
        for (AnchorDTO anchorDTO:list){
            AnchorMileageDTO anchorMileageDTO =new AnchorMileageDTO();
          String mileageNumber ="0.0";
          if(0!=index){
              AnchorDTO anchorDTOPt = list.get(index-1);
              double mileageNum=   haversineDistance(anchorDTOPt.getLatitude(),
                      anchorDTOPt.getLongitude(),
                      anchorDTO.getLatitude(),
                      anchorDTO.getLongitude()
                      );
              mileageNumber =String.format("%.1f",mileageNum);
              count+=Double.parseDouble(mileageNumber);

          }
          anchorMileageDTO.setMileageNumber(mileageNumber);
          anchorMileageDTO.setMileageNumberCount(String.format("%.1f",count));
          anchorMileageDTO.setName(anchorDTO.getName());
          anchorMileageDTO.setLatitude(anchorDTO.getLatitude());
          anchorMileageDTO.setLongitude(anchorDTO.getLongitude());
          anchorMileageDTO.setDepthNumber(String.valueOf(anchorDTO.getDepthNumber()));
            listAnchorMileageDTO.add(anchorMileageDTO);
          index++;
        }
        return new Result<List<AnchorMileageDTO>>().ok(listAnchorMileageDTO);
    }

    // 计算两点间的距离（单位：米）
    public static double haversineDistance(String lat1Str, String lon1Str, String lat2Str, String lon2Str) {

        double lat1 = Double.parseDouble(lat1Str);
        double lon1=Double.parseDouble(lon1Str);
        double lat2=Double.parseDouble(lat2Str);
        double lon2=Double.parseDouble(lon2Str);
        // 地球半径（单位：米）
        final int R = 6371000; // 米

        double latDistance = toRadians(lat2 - lat1);
        double lonDistance = toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c; // 返回结果单位为米
    }

    // 将角度转换为弧度
    private static double toRadians(double angle) {
        return Math.toRadians(angle);
    }

}